home *** CD-ROM | disk | FTP | other *** search
/ Loadstar 242 / 242.d81 / t.pack about < prev    next >
Text File  |  2022-08-26  |  13KB  |  478 lines

  1. u
  2.     S T A R   P A C K E R   1 . 2
  3.              by Lee Novak
  4.  
  5.  
  6.          [ALL SECRETS REVEALED]
  7.          [{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}]
  8.  
  9.     This article is for anyone who is
  10. interested in how this packer works.
  11. While the actual code was very
  12. difficult to write, the ideas behind
  13. it are rather simple.
  14.  
  15.     You might think: "How can a file
  16. be compressed? How can you construct
  17. a file without having all the data?"
  18. It doesn't seem possible.
  19.  
  20.     The idea I got from LS #135's
  21. article on LZS COMPRESSION was that
  22. any duplicated data can be packed.
  23. What's needed is a way to signal when
  24. something is to repeated. You also
  25. need to tell the unpacker where the
  26. original data is, and how much of it
  27. you need to repeat.
  28.  
  29.     How you go about this doesn't
  30. matter, just as long as it works! The
  31. LZS article talks of an unpacker that
  32. reads from a stream of bits only.
  33. This means that specific information
  34. (where repeat data is, etc.) might be
  35. split up between two or more bytes.
  36.  
  37.     I'm guessing that this method of
  38. varying bit-lengths provides the best
  39. compression, and maybe that's why the
  40. BIT IMPLODER is so good. But it sure
  41. sounded difficult. I didn't consider
  42. using this method for long.
  43.  
  44.  
  45.  [THE THEORY OF RARES]
  46.  [{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}]
  47.  
  48.     I knew this packer was going to
  49. use simpler byte-sized pieces of
  50. data. Every byte the unpacker would
  51. read in could have any value 0-255.
  52. At least one value must be reserved
  53. to tell the unpacker that compression
  54. information is to follow.
  55.  
  56.     What value to use? Zero? No way!
  57. There are lots of zeroes in almost
  58. every file! What about a number that
  59. is hardly ever used? Better. But some
  60. files would use this number more than
  61. others. What was needed was a custom
  62. value for each file.
  63.  
  64.     How about counting the number of
  65. occurrences for each byte? Aha! The
  66. least common byte, the RARE byte, is
  67. to signal when compression is used.
  68.  
  69.     The unpacker would read in the
  70. byte following the RARE and know it
  71. has special meaning. But there are so
  72. many possible ways that information
  73. might be packed. How would you tell
  74. the unpacker to duplicate five bytes
  75. (matches) located 117 bytes back?
  76.  
  77.     If two bytes followed the RARE,
  78. you COULD represent this information.
  79. But then, how would you tell the
  80. unpacker to copy 37 bytes located
  81. 9155 bytes back? We surely don't want
  82. to pass up the savings there! Hmm,
  83. maybe we need three bytes to follow
  84. the RARE. One byte would represent
  85. the number of matches, and the next
  86. two tell how far back to get them.
  87.  
  88.     So now, we would need FOUR bytes
  89. to signify even the shortest packing:
  90. one RARE then three bytes. So, what
  91. advantage is there in "compressing" a
  92. string of four matches? None at all.
  93. But there's bound to be lots and lots
  94. of four-byte matches in a file! Can't
  95. we use ANY of them?
  96.  
  97.     Hey, what if we use another RARE?
  98. The unpacker could check if a byte is
  99. either of these RARES, and follow a
  100. different unpacking formula for each.
  101. Why not three RARES? Okay! Why not
  102. four, or five, or even twenty RARES?
  103.  
  104.     Two problems with this. One: the
  105. unpacker code grows with each RARE
  106. you decide to add, because each RARE
  107. represents a compression all its own.
  108.  
  109.     And two: all normal, uncompressed
  110. bytes are just written to memory as-
  111. is. But sometimes, an uncompressed
  112. RARE is part of the file. On these
  113. occasions, TWO bytes are needed to
  114. represent that one byte. A RARE to
  115. say "Hey, here comes a rare!" and one
  116. byte to say "We want this one!".
  117.  
  118.     The second RARE is slightly less
  119. "rare" than the first. The third is
  120. even less so. Eventually, the bytes
  121. may become so common that it costs
  122. MORE to represent them as two bytes
  123. each than the potential savings using
  124. another type of compression may add.
  125.  
  126.  
  127.  [WHAT EACH RARE DOES]
  128.  [{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}]
  129.  
  130.     I did a lot of experimentation
  131. using different numbers of RARES and
  132. ways of packing the information. The
  133. most favorable all-purpose method of
  134. packing turned out to be one that
  135. uses the top eight RARES.
  136.  
  137.     Pretend you're an unpacker. You
  138. read along, splatting uncompressed
  139. bytes down without thought. Then you
  140. come across one of these RARE bytes.
  141. It's time to take the next byte, or
  142. bytes, more seriously. Here's EXACTLY
  143. what to do in these situations!
  144.  
  145.  RARE1, BYTE1:
  146.  
  147.     % 0000 0000
  148.       M{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  149.     3 matches, 3-258 bytes away
  150.  
  151.     Every possible value for BYTE1 is
  152. useful. ONE byte is saved for each
  153. 3-byte match. There were so many of
  154. these that a second RARE was added:
  155.  
  156.  RARE2, BYTE1:
  157.  
  158.     % 0000 0000
  159.       M{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  160.     3 matches, 259-514 bytes away
  161.  
  162.     Gathering 3-byte matches wasn't
  163. profitable after that, so all others
  164. are ignored.
  165.  
  166.  RARE3, BYTE1:
  167.  
  168.     % 0000 0000
  169.       M{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  170.     4 matches, 4-259 bytes away
  171.  
  172.     Each one of these saves TWO
  173. bytes. There are still larger matches
  174. close to the target string, but they
  175. are becoming less common. Time to
  176. break down the data byte into bits:
  177.  
  178.  RARE4, BYTE1:
  179.               P{SHIFT-*} 0=5 matches
  180.     % 0000 0000  1=6 matches
  181.       M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  182.       5-132 bytes away
  183.    or 6-133 bytes away
  184.  
  185.  RARE5, BYTE1:
  186.               P{SHIFT-*} 0=7 matches
  187.     % 0000 0000  1=8 matches
  188.       M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  189.       7-134 bytes away
  190.    or 8-135 bytes away
  191.  
  192.     These 2-byte compressions save
  193. between 3 and 6 bytes apiece. Things
  194. are thinning out even more now, but
  195. we still want anything that will make
  196. a profit. Let's add a data byte:
  197.  
  198.  RARE6, BYTE1, BYTE2:
  199.  
  200.     % 0000 0000   % 0000 0000
  201.       MR{SHIFT-*}{SHIFT--} MR{SHIFT-*}{SHIFT--}     M{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  202.        {SHIFT--}   high        low
  203.        {SHIFT--}   nybble      byte
  204.        {SHIFT--}    M{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  205.        {SHIFT--}  0-4095 bytes away
  206.        {SHIFT--}
  207.       4-19 matches
  208.  
  209.  RARE7, BYTE1, BYTE2:
  210.  
  211.     % 0000 0000   % 0000 0000
  212.       MR{SHIFT-*}{SHIFT--} MR{SHIFT-*}{SHIFT--}     M{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  213.        {SHIFT--}   high        low
  214.        {SHIFT--}   nybble      byte
  215.        {SHIFT--}    M{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  216.        {SHIFT--}  4096-8191 bytes away
  217.        {SHIFT--}
  218.       4-19 matches
  219.  
  220.     These 3-byte compressions save
  221. between 1 and 16 bytes apiece. We
  222. still need one more RARE to handle
  223. the rest of the possibilities:
  224.  
  225.  RARE8, BYTE1 (0):
  226.  
  227.     End of compression. RUN program.
  228.  
  229.  RARE8, BYTE1 (1-8):
  230.  
  231.     Add a specific uncompressed RARE.
  232.  
  233.  RARE8, BYTE1 (9), BYTE2:
  234.  
  235.     This unusual type of compression
  236. is for font data ONLY. If the exact
  237. REVERSE of the target string can be
  238. found exactly 1K earlier in the file,
  239. just like reversed font data, then we
  240. go back to copy 4-255 REVERSE bytes
  241. as specified in BYTE2.
  242.  
  243.     This EOR compression is probably
  244. only useful to STAR LINKED files. The
  245. cost of the related unpacking code is
  246. 34 bytes. This cost is recovered with
  247. the first 5 characters that can be
  248. packed this way!
  249.  
  250.  RARE8, BYTE1 (10-127), BYTE2, BYTE3:
  251.  
  252.     %00000000   %00000000   %00000000
  253.      {SHIFT--}M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT--}    M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}    M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  254.      {SHIFT--}  5-122    high byte   low byte
  255.      {SHIFT--} matches      M{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  256.      {SHIFT--}            0-65535 bytes away
  257.      Malways 0
  258.  
  259.     All remaining profitable matches
  260. are compressed this way. Since using
  261. this method costs 4 bytes each time,
  262. at least 5 characters must be packed
  263. with it to save at least one byte.
  264.  
  265.  RARE8, BYTE1 (128-255), BYTE2:
  266.  
  267.     %00000000   %00000000
  268.      {SHIFT--}M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT--}    M{SHIFT-*}{SHIFT-*}R{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT--}
  269.      {SHIFT--}  4-131  byte to repeat
  270.      {SHIFT--} repeats
  271.      {SHIFT--}
  272.      Malways 1
  273.  
  274.     This last one is known as RLE, or
  275. Run-Length-Encoding. It can be pretty
  276. useful for packing fonts, sprites, or
  277. anything which may have 4 or more
  278. identical bytes in a row.
  279.  
  280.     Now you know what does what, you
  281. get a better idea of the information
  282. on the packing screen. Here are the
  283. RARES one last time, with the
  284. categories they fall into:
  285.  
  286.   RARE1 - RARE5      = "short"
  287.   RARE6 - RARE7      = "medium"
  288.   RARE8 with 10-127  = "long"
  289.   RARE8 with 128-255 = "repeat"
  290.   RARE8 with 9       = "rvs font"
  291.  
  292.     The number of uncompressed RARES
  293. in the file isn't shown anywhere.
  294.  
  295.  
  296.  [TOIL AND TROUBLE]
  297.  [{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}]
  298.  
  299.     Why is this packer so slow?
  300. Actually it's not. You won't BELIEVE
  301. how much work is going on internally!
  302. The packer begins at the end of a
  303. file and works backwards. It searches
  304. for the MOST MATCHES as CLOSE TO the
  305. target string as possible.
  306.  
  307.     The packer begins this search for
  308. each 3-byte string a certain distance
  309. back from the string. How far back it
  310. goes depends on the CRUNCH MODE:
  311.  
  312.  Crunch Mode  How Far Back
  313.  {SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}  {SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}
  314.      1        1 page  (256 bytes)
  315.      2        2 pages (512 bytes)
  316.      3        4 pages (1K)
  317.